﻿
using B.S.BaseData.Domain.Interfaces;
using Microsoft.EntityFrameworkCore;
using Microsoft.EntityFrameworkCore.Diagnostics;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace B.S.BaseData.Domain.Implements
{
    /// <summary>
    /// 软删除拦截器，用于实现EF Core的软删除功能
    /// </summary>
    /// <remarks>
    /// 继承自<see cref="SaveChangesInterceptor"/>，
    /// 在保存变更时自动将删除操作转换为更新操作
    /// </remarks>
    public sealed class SoftDeleteInterceptor : SaveChangesInterceptor
    {
        /// <summary>
        /// 同步保存变更拦截方法
        /// </summary>
        /// <param name="eventData">DbContext事件数据</param>
        /// <param name="result">拦截结果</param>
        /// <returns>处理后的拦截结果</returns>
        public override InterceptionResult<int> SavingChanges(DbContextEventData eventData, InterceptionResult<int> result)
        {
            OnSavingChanges(eventData);
            return base.SavingChanges(eventData, result);
        }
    
        /// <summary>
        /// 异步保存变更拦截方法
        /// </summary>
        /// <param name="eventData">DbContext事件数据</param>
        /// <param name="result">拦截结果</param>
        /// <param name="cancellationToken">取消令牌</param>
        /// <returns>处理后的拦截结果任务</returns>
        public override ValueTask<InterceptionResult<int>> SavingChangesAsync(
            DbContextEventData eventData, 
            InterceptionResult<int> result,
            CancellationToken cancellationToken = default)
        {
            OnSavingChanges(eventData);
            return base.SavingChangesAsync(eventData, result, cancellationToken);
        }
    
        /// <summary>
        /// 处理保存变更时的软删除逻辑
        /// </summary>
        /// <param name="eventData">DbContext事件数据</param>
        /// <exception cref="ArgumentNullException">当DbContext为null时抛出</exception>
        private static void OnSavingChanges(DbContextEventData eventData)
        {
            // 检查DbContext是否为空
            ArgumentNullException.ThrowIfNull(eventData.Context);
            
            // 检测变更
            eventData.Context.ChangeTracker.DetectChanges();
            
            // 遍历所有变更的实体
            foreach (var entityEntry in eventData.Context.ChangeTracker.Entries())
            {
                // 如果是删除操作且实体实现了ISoftDeleteEntityWithDeleted接口
                if (entityEntry is { State: EntityState.Deleted, Entity: ISoftDeleteEntityWithDeleted softDeleteEntity })
                {
                    // 设置软删除标志
                    softDeleteEntity.IsDelete = true;
                    // 将删除状态改为修改状态
                    entityEntry.State = EntityState.Modified;
                }
            }
        }
    }
}

